package com.supor.aiot.websocket;

import android.content.Context;
import android.text.TextUtils;

import org.java_websocket.handshake.ServerHandshake;

import java.net.URI;
import java.util.concurrent.TimeUnit;

/**
 * ---------------------------------------------------------------- <br>
 * Copyright (C) 2014-2021, by het, ShenZhen, All rights reserved.  <br>
 * ---------------------------------------------------------------- <br>
 * <p>
 * 描述: websocket实现类 <br>
 * 作者: lei <br>
 * 日期: 2021/9/20 <br>
 */
public class WsImpl {

    public JWebSocketClient client;
    private static String TAG = "websocket";
    private URI webUri = null;
    private static OnReceiveMessage onReceiveMessage;
    private int connectionLostTimeout = (int) TimeUnit.SECONDS.toNanos(20);
    // private static OnReceiveMessageListener onReceiveMessageListener;

    public static void init(Context context, String host) {
        if (TextUtils.isEmpty(host)) {
            Logc.e(TAG, "host is null");
            return;
        }
        SingletonHolder.sInstance.initClientSet(context, host);
    }

    /**
     * 连接服务器
     * 
     * @param callback 连接回调
     * @return
     */
    public static WsImpl connect(final ConnectCallback callback) {
        SingletonHolder.sInstance.connectServer(new ConnectCallback() {
            @Override
            public void onSuccess(String id) {
                if (callback != null) {
                    callback.onSuccess(id);
                }
            }

            @Override
            public void onError(ErrorMessage error) {
                if (callback != null) {
                    callback.onError(error);
                }
            }
        });
        return SingletonHolder.sInstance;
    }

    /**
     * 断开连接
     */
    public static void disConnectionSocket() {
        SingletonHolder.sInstance.closeConnect();
    }

    /**
     * 重连websocket
     *
     * @throws Exception
     */
    public static void reConnectionWebsocket() throws Exception {
        SingletonHolder.sInstance.reConnectionSelfWebsocket();
    }

    /**
     * 是否client为空
     *
     * @return client为空
     */
    public static boolean isNullReconnectionWebsocket() {
        return SingletonHolder.sInstance.isNullReconnectionSelfWebsocket();
    }

    /**
     * websocket是否关闭
     *
     * @return 是否关闭
     */
    public static boolean isCloseConnectionWebsocket() {
        return SingletonHolder.sInstance.isCloseReconnectionSelfWebsocket();
    }

    public static void setOnReceiveMessage(OnReceiveMessage listener) {
        onReceiveMessage = listener;
    }


    /**
     * 设置丢失连接检查间隔
     *
     * @param timeout the interval in seconds
     */
    public void setConnectionLostTimeout(int timeout) {
        connectionLostTimeout = timeout;
    }

    private void initClientSet(Context context, String host) {
        webUri = URI.create(host);
        Logc.i(TAG, "webUri: " + webUri);
    }

    private void connectServer(final ConnectCallback connectCallback) {
        try {
            if (client == null) {
                client = new JWebSocketClient(webUri) {
                    @Override
                    public void onMessage(String message) {
                        Logc.d(TAG, "receive: " + message);
                        if (onReceiveMessage != null) {
                            onReceiveMessage.onReceived(message);
                        }
                    }

                    @Override
                    public void onOpen(ServerHandshake handshakedata) {
                        super.onOpen(handshakedata);
                        if (connectCallback != null)
                            connectCallback.onSuccess(handshakedata.getHttpStatusMessage());
                    }

                    @Override
                    public void onClose(int code, String reason, boolean remote) {
                        super.onClose(code, reason, remote);
                        Logc.d(TAG,
                                "onClose code: " + code + ", reason: " + reason + ", remote: " + remote);
                        if (connectCallback != null)
                            connectCallback.onError(new ErrorMessage(code, reason, remote));
                    }

                    @Override
                    public void onError(Exception ex) {
                        super.onError(ex);
                        Logc.e(TAG, "onError ex: " + ex.getMessage());
                        if (connectCallback != null) {
                            // connectCallback.onError(new ErrorMessage(ex));
                        }
                    }
                };
                client.setConnectionLostTimeout(connectionLostTimeout);
                client.connectBlocking();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
            Logc.e(TAG, "connect onError ex=" + e.getMessage());
            if (connectCallback != null) {
                connectCallback.onError(new ErrorMessage(e));
            }
        }
    }

    /**
     * websocket是否关闭
     *
     * @return 是否关闭
     */
    private boolean isCloseReconnectionSelfWebsocket() {
        if (client == null) {
            return true;
        }
        return client.isClosed();
    }

    /**
     * 是否client为空
     *
     * @return client为空
     */
    private boolean isNullReconnectionSelfWebsocket() {
        return client == null;
    }

    /**
     * 重连websocket
     * 
     * @throws Exception 
     */
    private void reConnectionSelfWebsocket() throws Exception {
        if (client != null) {
            try {
                client.reconnectBlocking();
            } catch (InterruptedException e) {
                e.printStackTrace();
                throw e;
            }
        }
    }

    /**
     * 发送消息
     *
     * @param message
     */
    public static void sendMessage(String message) {
        if (TextUtils.isEmpty(message)) {
            Logc.e(TAG, "Message sending cannot null ");
            return;
        }
        SingletonHolder.sInstance.send(message);
    }


    private void send(String message) {
        Logc.i(TAG, "message: " + message);

        if (client != null && client.isOpen()) {
            client.send(message);
        } else {
            Logc.e(TAG, "send() client error null");
        }
    }

    /**
     * 断开连接
     */
    private void closeConnect() {
        Logc.i(TAG, "closeConnect");

        try {
            if (null != client) {
                client.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            client = null;
        }
    }

    public interface OnReceiveMessage {
        void onReceived(String msg);
    }

    private static class SingletonHolder {
        static WsImpl sInstance = new WsImpl();

        private SingletonHolder() {
        }
    }

}
